package com.fin.quant.app.service;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.fin.quant.app.service.vo.DividendDto;
import com.fin.quant.common.DividendUtil;
import com.fin.quant.common.vo.DividendVO;
import com.fin.quant.domain.entity.AssetEntity;
import com.fin.quant.domain.service.AssetDaoService;
import com.fin.quant.domain.service.DividendDaoService;
import com.fin.quant.domain.service.DividendRpcDomainService;
import com.fin.quant.instra.mysql.model.Asset;
import com.fin.quant.instra.mysql.model.Dividend;
import com.fin.quant.instra.mysql.model.DividendHistory;
import com.fin.quant.rpc.proto.*;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class DividendService {

    @Autowired
    private DividendRpcDomainService dividendRpcDomainService;

    @Autowired
    private AssetDaoService assetDaoService;

    @Autowired
    private DividendDaoService dividendDaoService;


    public List<DividendDto> getUserDividend(Long userId) {
        return Lists.newArrayList();
    }

    public List<DividendDto> getMarketDividend() {
        List<Dividend> dividends = dividendDaoService.findRecommendAsset();
        List<Long> assetIdList = dividends.stream().map(Dividend::getAssetId).collect(Collectors.toList());
        List<DividendHistory> dividendHisList = dividendDaoService.findDividendHisList(assetIdList);
        //分析分红稳定性特征
        Map<Long, List<DividendHistory>> assetDividendHistoryMap = dividendHisList.stream().collect(Collectors.groupingBy(DividendHistory::getAssetId));



        return Lists.newArrayList();
    }


    /**
     * 获取实时股息率
     *
     * @param assetId
     */
    public void getCurrentDividendYield(long assetId) {
        AssetEntity asset = assetDaoService.findById(assetId);
        log.info("asset={}", JSON.toJSONString(asset));
        if (asset == null) {
            return;
        }
        GetCurrentPriceRequest request = GetCurrentPriceRequest.newBuilder()
                .setAssetCode(asset.getAssetCode().replace(".SH", ""))
                .setMarket(asset.getMarket())
                .setAssetType(asset.getAssetType())
                .build();
        GetCurrentPriceResponse currentPrice = dividendRpcDomainService.getCurrentPrice(request);
        if (currentPrice.getCode() != 0) {
            log.error("无法获取实时价格信息. assetId={}", assetId);
            return;
        }

        Dividend dividend = dividendDaoService.findDividendByAssetId(assetId);
        if (dividend == null) {
            return;
        }
        //实时股息率=当前价格/最近一年分红金额每股
        double dividendYield = dividend.getAmountPerShare().doubleValue() / currentPrice.getCurrentPrice();

        Dividend updateDividend = new Dividend();
        updateDividend.setId(dividend.getId());
        updateDividend.setCurrentPrice(BigDecimal.valueOf(currentPrice.getCurrentPrice()));
        updateDividend.setDividendYield(BigDecimal.valueOf(dividendYield));
        dividendDaoService.updateDividend(updateDividend);
    }

    /**
     * 获取实时股息率
     *
     * @param assetId
     */
    public void getCloseDividendYield(long assetId) {
        AssetEntity asset = assetDaoService.findById(assetId);
        log.info("asset={}", JSON.toJSONString(asset));
        if (asset == null) {
            return;
        }
        GetHistoryPriceRequest request = GetHistoryPriceRequest.newBuilder()
                .setAssetCode(asset.getAssetCode().replace(".SH", ""))
                .setMarket(asset.getMarket())
                .setAssetType(asset.getAssetType())
                .build();
        GetHistoryPriceResponse historyPrice = dividendRpcDomainService.getHistoryPrice(request);
        log.info("getCloseDividendYield.assetId={} closePrice={}", assetId, historyPrice.getClosePrice());
        if (historyPrice.getCode() != 0) {
            log.error("无法获取历史价格信息. assetId={}", assetId);
            return;
        }

        Dividend dividend = dividendDaoService.findDividendByAssetId(assetId);
        if (dividend == null) {
            return;
        }
        //实时股息率=当前价格/最近一年分红金额每股
        double dividendYield = dividend.getAmountPerShare().doubleValue() / historyPrice.getClosePrice();

        Dividend updateDividend = new Dividend();
        updateDividend.setId(dividend.getId());
        updateDividend.setCurrentPrice(BigDecimal.valueOf(historyPrice.getClosePrice()));
        updateDividend.setDividendYield(BigDecimal.valueOf(dividendYield));
        dividendDaoService.updateDividend(updateDividend);
    }

    public void updateAssetDividendInfo(long assetId) {
        AssetEntity asset = assetDaoService.findById(assetId);
        log.info("asset={}", JSON.toJSONString(asset));
        if (asset == null) {
            return;
        }

        GetDividendInfoRequest request = GetDividendInfoRequest.newBuilder()
                .setAssetCode(asset.getAssetCode().replace(".SH", ""))
                .setAssetId(assetId)
                .setMarket(asset.getMarket())
                .setAssetType(asset.getAssetType())
                .build();
        GetDividendInfoResponse dividendInfo = dividendRpcDomainService.getDividendInfo(request);
        if (dividendInfo.getCode() != 0) {
            log.error("无法获取分红信息. assetId={}", assetId);
            return;
        }

        List<DividendInfo> dividendInfosList = dividendInfo.getDividendInfosList();
        if (CollectionUtils.isEmpty(dividendInfosList)) {
            return;
        }

        List<DividendHistory> dividendHistoryList = dividendInfosList.stream().map(dividendInfo1 -> {
            try {
                DividendHistory dividendHistory = new DividendHistory();

                dividendHistory.setAssetId(assetId);
                if (StringUtils.isNotBlank(dividendInfo1.getReportDate())) {
                    dividendHistory.setFiscalYear(Integer.parseInt(StringUtils.left(dividendInfo1.getReportDate(), 4)));
                } else {
                    dividendHistory.setFiscalYear(0);
                }
                //TODO
                dividendHistory.setAmount(BigDecimal.valueOf(0));
                //现金分红，指10股分红，需要除以10
                dividendHistory.setAmountPerShare(BigDecimal.valueOf(dividendInfo1.getCashDividendRatio() / 10));
                dividendHistory.setFrequency(dividendInfo1.getDividendPeriod());
                //TODO 这两个指去哪里获取
                dividendHistory.setGrowthRate(BigDecimal.valueOf(0));
                dividendHistory.setPayoutRatio(BigDecimal.valueOf(0));
                if (StringUtils.isNoneBlank(dividendInfo1.getExDividendDate())) {
                    dividendHistory.setExDividendDate(DateUtil.parse(dividendInfo1.getExDividendDate(), "yyyy-MM-dd"));
                }
                if (StringUtils.isNotBlank(dividendInfo1.getPaymentDate())) {
                    dividendHistory.setPaymentDate(DateUtil.parse(dividendInfo1.getPaymentDate(), "yyyy-MM-dd"));
                }
                dividendHistory.setRemark(dividendInfo1.getDividendNote());
                Date createdAt = new Date();
                dividendHistory.setCreatedAt(createdAt);
                dividendHistory.setUpdatedAt(createdAt);

                return dividendHistory;
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
        }).collect(Collectors.toList());
        dividendDaoService.save(dividendHistoryList);

        List<DividendVO> collect = dividendHistoryList.stream().map(dividendHistory -> {
            DividendVO dividendVO = new DividendVO();
            dividendVO.setFiscalYear(dividendHistory.getFiscalYear());
            dividendVO.setAmountPerShare(dividendHistory.getAmountPerShare());
            dividendVO.setFrequency(dividendHistory.getFrequency());
            return dividendVO;
        }).collect(Collectors.toList());
        Pair<Double, Integer> yearDividendPerSharePair = DividendUtil.getYearDividendPerShare(collect);
        if (yearDividendPerSharePair != null) {
            double yearDividendPerShare = yearDividendPerSharePair.getLeft();

            Dividend assetDividend = dividendDaoService.findDividendByAssetId(assetId);
            if (assetDividend == null) {
                //insert dividend
                Dividend dividend = new Dividend();
                dividend.setAssetId(assetId);
                dividend.setFiscalYear(0);
                dividend.setCurrentPrice(BigDecimal.ZERO);
                dividend.setAmountPerShare(BigDecimal.ZERO);
                dividend.setDividendYield(BigDecimal.ZERO);
                dividend.setAnnualDividend(BigDecimal.ZERO);
                dividend.setFrequency("");
                dividend.setRemark("");
                dividend.setCreatedAt(new Date());
                dividend.setUpdatedAt(new Date());
                dividendDaoService.saveDividend(dividend);
                assetDividend = dividend;
            }

            Dividend updateDividend = new Dividend();
            updateDividend.setId(assetDividend.getId());
            updateDividend.setFiscalYear(yearDividendPerSharePair.getRight());
            updateDividend.setAmountPerShare(BigDecimal.valueOf(yearDividendPerShare));
            dividendDaoService.updateDividend(updateDividend);
        }

    }
}
